using UnityEngine;
using System;

namespace GGameFramework.Event
{
    [CreateAssetMenu(menuName = "EventSO/Common/Event")]
    public class GameEvent : ScriptableObject
    {
        [TextArea,SerializeField] 
        private string description = "事件描述";
        
        private event Action OnEvent;
        public int HandlersCount => OnEvent?.GetInvocationList().Length ?? 0;
        public void Raise() => OnEvent?.Invoke();

        public void Register(IListener listener) => Register(listener.OnEventRaised);
        public void Register(Action handler)
        {
            OnEvent -= handler;
            OnEvent += handler;
        }

        public void Unregister(IListener listener) => Unregister(listener.OnEventRaised);
        public void Unregister(Action handler) => OnEvent -= handler;

    }
    
     public abstract class GameEvent<T> : ScriptableObject
    {
        [TextArea,SerializeField] 
        private string description = "事件描述";
        
        private event Action<T> OnEvent;
        public int HandlersCount => OnEvent?.GetInvocationList().Length ?? 0;

        public void Raise(T arg) => OnEvent?.Invoke(arg);

        public void Register(IListener<T> listener) => Register(listener.OnEventRaised);
        public void Register(Action<T> handler)
        {
            OnEvent -= handler;
            OnEvent += handler;
        }

        public void Unregister(IListener<T> listener) => Unregister(listener.OnEventRaised);
        public void Unregister(Action<T> handler) => OnEvent -= handler;
    }
     
    [CreateAssetMenu(menuName = "EventSO/Common/Int Event")]
    public class IntGameEvent : GameEvent<int> { }
    
    [CreateAssetMenu(menuName = "EventSO/Common/String Event")]
    public class StringGameEvent : GameEvent<string> { }
    
    [CreateAssetMenu(menuName = "EventSO/Common/Bool Event")]
    public class BoolGameEvent : GameEvent<bool> { }
    
    [CreateAssetMenu(menuName = "EventSO/Common/Float Event")]
    public class FloatGameEvent : GameEvent<float> { }
    
    [CreateAssetMenu(menuName = "EventSO/Common/Float Event")]
    public class Vector3GameEvent : GameEvent<Vector3> { }
    
    
    public abstract class GameEvent<T, U> : ScriptableObject
    {
        private event Action<T, U> OnEvent;
        public int HandlersCount => OnEvent?.GetInvocationList().Length ?? 0;

        public void Raise(T arg0, U arg1) => OnEvent?.Invoke(arg0, arg1);

        public void Register(IListener<T, U> listener) => Register(listener.OnEventRaised);
        public void Register(Action<T, U> listener)
        {
            OnEvent -= listener;
            OnEvent += listener;
        }
        public void Unregister(IListener<T, U> listener) => Unregister(listener.OnEventRaised);
        public void Unregister(Action<T, U> listener) => OnEvent -= listener;
}

    // public abstract class GameEvent<T, U, V> : ScriptableObject
    // {
    //     private event Action<T, U, V> OnEvent;
    //     public int HandlersCount => OnEvent?.GetInvocationList().Length ?? 0;
    //
    //     public void Raise(T arg0, U arg1, V arg2) => OnEvent?.Invoke(arg0, arg1, arg2);
    //
    //     public void Register(IListener<T, U, V> listener) => Register(listener.OnEventRaised);
    //     public void Register(Action<T, U, V> listener)
    //     {
    //         OnEvent -= listener;
    //         OnEvent += listener;
    //     }
    //
    //     public void Unregister(IListener<T, U, V> listener) => Unregister(listener.OnEventRaised);
    //     public void Unregister(Action<T, U, V> listener) => OnEvent -= listener;
    // }
    //
    // public abstract class GameEvent<T, U, V, W> : ScriptableObject
    // {
    //     private event Action<T, U, V, W> OnEvent;
    //     public int HandlersCount => OnEvent?.GetInvocationList().Length ?? 0;
    //
    //     public void Raise(T arg0, U arg1, V arg2, W arg3) => OnEvent?.Invoke(arg0, arg1, arg2, arg3);
    //     
    //     public void Register(IListener<T, U, V, W> listener) => Register(listener.OnEventRaised);
    //     public void Register(Action<T, U, V, W> listener)
    //     {
    //         OnEvent -= listener;
    //         OnEvent += listener;
    //     }
    //
    //     public void Unregister(IListener<T, U, V, W> listener) => Unregister(listener.OnEventRaised);
    //     public void Unregister(Action<T, U, V, W> listener) => OnEvent -= listener;
    // }
}

